﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Mono.Unix;
using Mono.Unix.Native;


// SIRP Experimental Firmware
// Entry Point
// (c) 2014 Chris Burri. MIT License applies. 
// See http://niston.wordpress.com

namespace sdd
{
    class Program
    {
        private static bool shutdownSignal = false;
        
        public static ManualResetEvent waitHandle = new ManualResetEvent(false);
        public static Director Director;
           
        static int Main(string[] args)
        {
            // start up Director
            Director = new Director();
            Director.Initialize();

            // See http://stackoverflow.com/questions/9391466/mono-application-using-console-cancelkeypress-cannot-be-run-in-background
            if (Director.IsRunningOnMono)
            {
                // install signal handling
                setupUnixSignalHandling();
            }
            else
            {
                // install ctrl-c procedure
                Console.CancelKeyPress += delegate
                {;
                    Console.WriteLine("CTRL-C received.");
                    waitHandle.Set();
                };
            }

            // wait for exit signal
            waitHandle.WaitOne();

            // EXIT
            shutdownSignal = true;
            bool wasOnMono = Director.IsRunningOnMono;

            // VOODOO: let it settle
            System.Threading.Thread.Sleep(616);

            // tear everythinig down
            Director = null;

            // doesn't terminate on mono? whack it!
            if (wasOnMono) { Process.GetCurrentProcess().Kill(); }
            
            // goodbye
            return 0;
        }

    #region Unix Signal Handling
        private static void setupUnixSignalHandling()
        {
            Thread newthread = new Thread(new ThreadStart(sigHndlr));
            newthread.Start();
        }

        private static void sigHndlr()
        {
            UnixSignal[] signals = new UnixSignal []
                {
                    new UnixSignal(Signum.SIGINT),
                    new UnixSignal(Signum.SIGTERM),
                    new UnixSignal(Signum.SIGQUIT),
                    new UnixSignal(Signum.SIGHUP)
                };

            while (!shutdownSignal)
            {
                int index = UnixSignal.WaitAny(signals, -1);
                Signum signal = signals[index].Signum;
                sigHandler(signal);
                System.Threading.Thread.Sleep(25);
            }
        }

        private static void sigHandler(Signum signal)
        {
            switch (signal)
            {
                case Signum.SIGINT:
                    Console.WriteLine("SIGINT (Ctrl-C) received.");
                    shutdownSignal = true;
                    waitHandle.Set();
                    break;
                case Signum.SIGTERM:
                    Console.WriteLine("SIGTERM received.");
                    shutdownSignal = true;
                    waitHandle.Set();
                    break;
                case Signum.SIGSTOP:
                    Console.WriteLine("SIGSTOP received.");
                    shutdownSignal = true;
                    waitHandle.Set();
                    break;
                case Signum.SIGQUIT:
                    Console.WriteLine("SIGQUIT received.");
                    shutdownSignal = true;
                    waitHandle.Set();
                    break;
                case Signum.SIGHUP:
                    Console.WriteLine("SIGHUP received.");
                    // reload config
                    break;
            }
        }
    #endregion
    }
}
